package com.cxria.script

import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.locks.ReentrantLock

class VideoAnalysis{

    def videoInfos = [:]

    def tryLine = {String videoNameInfo, String videoPath, int mSize ->
        def isFFprobe = false
        def tryIndex = 0
        try{
            def videoSize = videoInfos[videoNameInfo]
            def(prefix, dir, filenameInfo) = videoNameInfo.split('/')
            def(filename, suffix) = filenameInfo.split('\\.')
            def isNext = true
            def outPath = "${videoPath}/${dir}-${filename}.${suffix}"
            def videoHalfSize = videoSize / 2 as BigInteger
            while (!isFFprobe && isNext){
                def headStartBit = tryIndex *  mSize as long
                def headEndBit = (tryIndex + 1) * mSize - 1  as long
                def footStartBit = videoSize - (tryIndex + 1) * mSize  as long
                def footEndBit = videoSize - tryIndex * mSize -1  as long
                if(headEndBit + 1 >= videoHalfSize){
                    headEndBit = videoHalfSize - 1 as long
                    footStartBit = headEndBit + 1 as long
                    isNext = false
                }
                def url = "http://trans.gaiamount.com/${videoNameInfo}"
                def headPath = "${videoPath}/${dir}-${filename}-${tryIndex}-head.${suffix}"
                def footPath = "${videoPath}/${dir}-${filename}-${tryIndex}-foot.${suffix}"
                def headRange = "-r ${headStartBit}-${headEndBit}"
                def footRange = "-r ${footStartBit}-${footEndBit}"
                def headCurlCmd = "curl ${headRange} -o ${headPath} ${url}"
                headCurlCmd.exec()
                def footCurlCmd = "curl ${footRange} -o ${footPath} ${url}"
                footCurlCmd.exec()

                FileUtils.append(outPath, headPath, headStartBit)
                FileUtils.append(outPath, footPath, footStartBit)

                def rmOldVideo = "rm -f ${headPath} ${footPath}"
                rmOldVideo.exec()

                def ffprobeCmd = "ffprobe ${outPath}"
                isFFprobe = ffprobeCmd.exec().success
                if(!isNext && !isFFprobe){
                    println "\nffprobe 出错了：${videoNameInfo}"
                }
                tryIndex ++
                print '.'
            }
            def cleanCmd = "rm -f ${outPath}"
            cleanCmd.exec()
        } catch(e) {
            println "${videoNameInfo} 错误： ${e.message}"
        }
        [isFFprobe, tryIndex]
    }

    void start(List currentVideoNames, String xlsName, int threadNum, int m, String rootPath){
        def videoPath = "${rootPath}/video"
        def mSize = 1024 * 1024 * m
        def i = new AtomicInteger(0)
        def lineSumNum = currentVideoNames.size()
        def threadTaskNum = lineSumNum / threadNum as int
        def tasks = []
        def execl = new SuperExecl()
        def workbook = execl.createWorkbook(xlsName)
        def sheet = execl.createSheet(workbook, [fileName: 3000, fileSize: 3000, cutSize: 3000])
        def lock = new ReentrantLock()
        (0..threadNum - 1).each { threadIndex ->
            def startLine = threadIndex * threadTaskNum
            def endLine = (threadIndex + 1) * threadTaskNum - 1
            if(threadIndex == threadNum - 1){
                endLine = lineSumNum - 1
            }
            def videoNames = currentVideoNames[startLine..endLine]
            def task = {
                try {
                    def lineNumForThread = 0
                    videoNames.each { videoNameInfo ->
                        try{
                            def videoSize = videoInfos[videoNameInfo]
                            def lineStart = System.currentTimeMillis()
                            def tryNum = 5
                            def videoM = videoSize / 1024 / 1024 as int
                            def parameters = [videoNameInfo as String, videoPath as String, mSize as int]
                            def(isFFprobe, tryIndex) = FuncUtils.tryFunc(tryNum, tryLine, parameters){ isFFprobe2, tryIndex2 ->
                                isFFprobe2
                            }
                            def lineEnd = System.currentTimeMillis()
                            def cutM = -1
                            if(isFFprobe){
                                cutM = tryIndex * m
                            }
                            try {
                                lock.tryLock(5000, TimeUnit.MILLISECONDS)
                                println "[line: ${i.intValue()}, thread: [${threadIndex}, ${lineNumForThread}], name： ${videoNameInfo}, size: ${videoM}M, cut: ${cutM}M, time: ${lineEnd - lineStart}]"
                                execl.writeLine(sheet, i.intValue() + 1, [videoNameInfo, videoM, cutM])
                                execl.writeToFile(xlsName, workbook)
                                i.addAndGet(1)
                            } finally {
                                lock.unlock()
                            }
                            lineNumForThread ++
                        } catch(e){
                            println "${videoNameInfo} 错误： ${e.message}"
                            e.printStackTrace()
                        }
                    }
                } catch(e) {
                    println e.message
                }
            }
            tasks << task
        }
        def executorService = Executors.newFixedThreadPool(threadNum)
        def startTime = System.currentTimeMillis()
        executorService.invokeAll(tasks)
        executorService.shutdown()
        def endTime = System.currentTimeMillis()
        println "用时：${(endTime - startTime) / 1000 / 60}分！ "
    }

    void putVideoInfo(List lines){
        lines.each { line ->
            def lineInfo = line.split('\t')
            def videoNameInfo = lineInfo[0]
            def videoSize = lineInfo[1] as BigInteger
            videoInfos.put(videoNameInfo, videoSize)
        }
    }

    static void main(String[] args) {
        def cmdUtils = new CmdUtils()
        String.metaClass.exec = {
            cmdUtils.execute(delegate)
        }
        def rootPath = '/usr/local/qshell'
        def qfileIndex
        try{
            qfileIndex = args[0] as int
        } catch(e) {
            qfileIndex = 0
        }
        def qshellListFile = new File("${rootPath}/qshell-result${qfileIndex}.txt")
        def bigLines = qshellListFile.readLines()
        def bigLineSize = bigLines.size()
        def startLineBig
        def endLineBig
        def threadNum
        def m
        try{
            startLineBig = args[1] as int
            endLineBig = args[2] as int
            threadNum = args[3] as int
            m = args[4] as int
        } catch(e) {
            println "参数异常[${e.message}]，遍历全部"
            startLineBig = 0
            endLineBig = bigLineSize
            threadNum = 4
            m = 10
        }
        if(endLineBig + 1 > bigLineSize){
            endLineBig = bigLineSize - 1
        }
        println "从第${startLineBig}行到第${endLineBig}行，前后各${m}M，${threadNum}个线程"
        def va = new VideoAnalysis()
        def currentLines = bigLines[startLineBig..endLineBig]
        va.putVideoInfo(currentLines)
        def xlsName = "${rootPath}/video-${startLineBig}-${endLineBig}.xlsx"
        va.start(va.videoInfos.keySet() as List, xlsName, threadNum, m, rootPath)
    }

}